#!/bin/bash
###
# @Author: admin@attacker.club
# @Date: 2022-07-30 18:03:20
# @LastEditTime: 2025-10-20 23:21:09
# @Description: vsftpd FTP服务器安装脚本
# @支持系统: CentOS 7/8/9, Ubuntu 18.04/20.04/22.04/24.04
# @功能：
#   1. 自动检测操作系统类型
#   2. 支持自定义FTP端口
#   3. 自动生成安全密码
#   4. 主动/被动模式配置
### 

# 基础设置
set -e  # 遇到错误立即退出

# 全局变量
FTP_PORT=21
FTP_USER="ftpcenter"
FTP_HOME="/home/ftpcenter"
PASV_MIN_PORT=35000
PASV_MAX_PORT=35500 

# 判断是否root用户
check_root() {
    if [ $(id -u) -ne 0 ]; then
        error "此脚本必须以root用户运行！"
        exit 1
    fi
}

#### -----------  打印颜色 ----------- #### 
#### -----------  打印颜色 ----------- #### 
info() { echo -e "\e[34m[INFO]\e[0m $1"; }
warn() { echo -e "\e[33m[WARN]\e[0m $1"; }
error() { echo -e "\e[31m[ERROR]\e[0m $1" >&2; }
success() { echo -e "\e[32m[SUCCESS]\e[0m $1"; }

# 检测操作系统
detect_os() {
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        OS=$ID
        OS_VERSION=$VERSION_ID
        info "检测到系统: $NAME $VERSION_ID"
    else
        error "无法检测操作系统版本"
        exit 1
    fi

    # 验证系统是否支持
    case $OS in
        centos|rhel|rocky|almalinux)
            if [[ ! "$OS_VERSION" =~ ^[7-9] ]]; then
                error "仅支持 CentOS/RHEL 7/8/9"
                exit 1
            fi
            PKG_MANAGER="yum"
            ;;
        ubuntu|debian)
            PKG_MANAGER="apt"
            ;;
        *)
            error "不支持的操作系统: $OS"
            error "仅支持: CentOS 7/8/9, Ubuntu 18.04+"
            exit 1
            ;;
    esac
    success "系统检测通过"
}

# 安装vsftpd
Install() {
    info "正在安装vsftpd..."
    
    # 清理历史安装
    systemctl stop vsftpd 2>/dev/null || true
    
    if [ "$PKG_MANAGER" = "yum" ]; then
        # CentOS/RHEL系统
        yum remove vsftpd -y 2>/dev/null || true
        rm -rf /etc/vsftpd/
        yum install -y vsftpd net-tools
    else
        # Ubuntu/Debian系统
        apt-get remove --purge vsftpd -y 2>/dev/null || true
        rm -rf /etc/vsftpd/
        apt-get update
        apt-get install -y vsftpd net-tools
    fi

    # 验证安装
    if ! command -v vsftpd &>/dev/null; then
        error "vsftpd安装失败！"
        exit 1
    fi
    
    success "vsftpd安装完成: $(vsftpd -v 2>&1 | head -n1)"
}

# 配置vsftpd
Set_conf() {
    info "正在配置vsftpd..."
    
    # 创建配置目录
    mkdir -p /etc/vsftpd

    # 创建主配置文件
    cat >/etc/vsftpd.conf <<'VSFTPDCONF'
# 基础设置
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022

# 日志设置
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
xferlog_file=/var/log/vsftpd.log

# 安全设置
pam_service_name=vsftpd
tcp_wrappers=YES
userlist_deny=NO
chroot_local_user=YES
allow_writeable_chroot=YES
seccomp_sandbox=NO

# 端口配置
listen=YES
listen_ipv6=NO
VSFTPDCONF

    # 添加端口配置
    echo "listen_port=$FTP_PORT" >> /etc/vsftpd.conf
    
    # 被动模式配置（默认注释）
    cat >>/etc/vsftpd.conf <<PASVCONF

# 被动模式配置 (取消注释启用)
# pasv_enable=YES
# pasv_min_port=$PASV_MIN_PORT
# pasv_max_port=$PASV_MAX_PORT
# pasv_address=<服务器公网IP>
PASVCONF

    # Ubuntu特殊配置
    if [ "$OS" = "ubuntu" ] || [ "$OS" = "debian" ]; then
        sed -i 's/pam_service_name=vsftpd/pam_service_name=ftp/' /etc/vsftpd.conf
        info "已适配Ubuntu PAM配置"
    fi
    
    # 为兼容性创建配置文件副本
    cp /etc/vsftpd.conf /etc/vsftpd/vsftpd.conf 2>/dev/null || true
    
    success "vsftpd配置完成"
}

# 启动服务
Run() {
    # 添加FTP用户
    info "创建FTP用户: $FTP_USER"
    userdel -r $FTP_USER 2>/dev/null || true
    useradd -m -d $FTP_HOME -s /bin/bash $FTP_USER
    
    # 设置目录权限
    chmod 755 $FTP_HOME
    
    # 创建上传目录
    mkdir -p $FTP_HOME/upload
    chown $FTP_USER:$FTP_USER $FTP_HOME/upload
    
    success "FTP用户创建完成"

    # 服务管理
    info "启动vsftpd服务..."
    systemctl daemon-reload
    systemctl enable vsftpd
    systemctl restart vsftpd
    
    # 等待服务启动
    sleep 2
    
    # 验证服务状态
    if systemctl is-active --quiet vsftpd; then
        success "vsftpd服务启动成功"
    else
        error "vsftpd服务启动失败！"
        systemctl status vsftpd --no-pager
        exit 1
    fi
    
    # 验证端口监听
    if netstat -tuln 2>/dev/null | grep -q ":$FTP_PORT " || ss -tuln 2>/dev/null | grep -q ":$FTP_PORT "; then
        success "vsftpd正在监听$FTP_PORT端口"
    else
        warn "未检测到$FTP_PORT端口监听，请手动检查"
    fi
}

# 设置密码
set_passwd() {
    info "生成安全密码..."
    pwd=$(tr -dc 'A-Za-z0-9!@#$%^&*' </dev/urandom | head -c 16)
    echo "$FTP_USER:$pwd" | chpasswd
    success "密码设置完成"
    
    # 保存账号信息
    cat > ftp_info.txt <<FTPINFO
========== vsftpd FTP服务器信息 ==========
用户名: $FTP_USER
密码: $pwd
端口: $FTP_PORT
FTP目录: $FTP_HOME
上传目录: $FTP_HOME/upload
连接模式: 主动模式

启用被动模式:
1. 编辑 /etc/vsftpd.conf
2. 取消pasv相关配置注释
3. 设置pasv_address为服务器公网IP
4. 防火墙开放端口范围: $PASV_MIN_PORT-$PASV_MAX_PORT
5. 重启vsftpd服务
====================================================
FTPINFO
    
    chmod 600 ftp_info.txt
}

# 显示连接信息
Show_connection_info() {
    # 获取服务器IP
    ip=$(hostname -I 2>/dev/null | awk '{print $1}')
    if [ -z "$ip" ]; then
        ip=$(curl -s ifconfig.me || curl -s icanhazip.com || curl -s ipinfo.io/ip)
    fi
    [ -z "$ip" ] && ip="<服务器IP>"
    
    echo ""
    echo "========================================"
    info "FTP服务器连接信息:"
    echo "========================================"
    echo "主机: $ip"
    echo "用户名: $FTP_USER"
    echo "密码: $pwd"
    echo "端口: $FTP_PORT"
    echo ""
    
    info "使用FTP客户端连接:"
    echo "  - FileZilla"
    echo "  - WinSCP"
    echo "  - 命令行: ftp $ip $FTP_PORT"
    echo ""
    
    info "使用curl命令测试:"
    echo "  # 上传文件"
    echo "  echo 'Hello FTP' > test.txt"
    echo "  curl -T test.txt ftp://$ip:$FTP_PORT/upload/ --user $FTP_USER:$pwd"
    echo ""
    echo "  # 下载文件"
    echo "  curl ftp://$ip:$FTP_PORT/upload/test.txt --user $FTP_USER:$pwd"
    echo ""
    echo "  # 列出文件"
    echo "  curl ftp://$ip:$FTP_PORT/upload/ --user $FTP_USER:$pwd"
    echo "========================================"
}

# 主程序
Main() {
    check_root
    detect_os
    
    echo ""
    info "========== 开始安装vsftpd FTP服务器 =========="
    echo ""
    
    # 端口交互
    read -p "请输入FTP端口 [默认21，直接回车使用默认]: " input_port
    if [[ -n "$input_port" && "$input_port" =~ ^[0-9]+$ ]]; then
        if [ "$input_port" -gt 0 ] && [ "$input_port" -lt 65536 ]; then
            FTP_PORT=$input_port
            info "将使用自定义端口: $FTP_PORT"
        else
            warn "端口范围无效，使用默认端口: 21"
        fi
    else
        info "使用默认端口: 21"
    fi
    echo ""
    
    Install
    Set_conf
    Run
    set_passwd
    
    echo ""
    success "========== vsftpd安装完成 =========="
    echo ""
    
    cat ftp_info.txt
    echo ""
    
    Show_connection_info
    
    echo ""
    warn "重要提示:"
    warn "1. 防火墙需放行端口: $FTP_PORT(控制) 20(主动模式数据)"
    warn "2. 被动模式需配置pasv端口范围并放行: $PASV_MIN_PORT-$PASV_MAX_PORT"
    warn "3. 账号信息已保存到: $(pwd)/ftp_info.txt"
    warn "4. 服务管理命令: systemctl {start|stop|restart|status} vsftpd"
    echo ""
    
    # 防火墙配置提示
    if command -v firewall-cmd &>/dev/null; then
        info "防火墙配置命令(firewalld):"
        echo "  firewall-cmd --permanent --add-port=$FTP_PORT/tcp"
        echo "  firewall-cmd --permanent --add-port=20/tcp"
        echo "  firewall-cmd --permanent --add-service=ftp"
        echo "  firewall-cmd --reload"
    elif command -v ufw &>/dev/null; then
        info "防火墙配置命令(ufw):"
        echo "  ufw allow $FTP_PORT/tcp"
        echo "  ufw allow 20/tcp"
        echo "  ufw reload"
    fi
    echo ""
}

Main